package sync_log_table

import (
	"go-kvsql/db/pebbledb"
	"go-kvsql/sync_log_table/sync_log"
	"go-kvsql/sync_log_table/sync_log_array"
	"reflect"
	"sort"
	"sync/atomic"
)

type SyncLogTable struct {
	db    *pebbledb.PebbleDB
	logId uint64
}

func NewSyncLogTable(dbPath string, tableName string) (*SyncLogTable, error) {
	db, err := pebbledb.NewDefaultPebbleDB(dbPath + "/" + tableName + "/sync-log")
	if err != nil {
		return nil, err
	}
	return &SyncLogTable{db: db}, nil
}

func (this *SyncLogTable) ContainsData() bool {
	return this.db.ContainsData()
}

func (this *SyncLogTable) Count() int {
	return this.db.Count()
}

func (this *SyncLogTable) Insert(logType sync_log.LogType, key int64, value interface{}) (*sync_log.SyncLog, error) {
	syncLog, err := sync_log.NewSyncLog(atomic.AddUint64(&this.logId, 1), logType, key, value)
	if err != nil {
		return nil, err
	}
	err = this.db.Set(syncLog.LogKeyBytes, syncLog.ValueBytes)
	if err != nil {
		return nil, err
	}
	return syncLog, nil
}

func (this *SyncLogTable) Delete(key []byte) error {
	return this.db.Delete(key)
}

func (this *SyncLogTable) SortArray(valueType reflect.Type) (sync_log_array.SyncLogArray, error) {
	table := this.db.Table()
	count := len(table)
	syncLogArray := make(sync_log_array.SyncLogArray, 0, count)
	for keyString, valueString := range table {
		logId, logType, key, err := sync_log.DecodeLogKey(keyString)
		if err != nil {
			return nil, err
		}
		var value interface{}
		if logType == sync_log.Del {
			value = ""
		} else {
			value, err = sync_log.DecodeValue([]byte(valueString), valueType)
			if err != nil {
				return nil, err
			}
		}
		syncLog, err := sync_log.NewSyncLog(logId, logType, key, value)
		if err != nil {
			return nil, err
		}
		syncLogArray = append(syncLogArray, *syncLog)
	}
	sort.Sort(syncLogArray)
	return syncLogArray, nil
}

func (this *SyncLogTable) Clear() {
	this.db.Clear()
}
